#ifndef __CLI_PARSE__LINE_H__
#define __CLI_PARSE__LINE_H__

#include "structs.h"

#include <vector>
#include "../../Epsilon/STL.h"


namespace Underlight
{
  class Sector;
  class SectorWall;
  class Level;

  class Line
  {
  public:
    Line (const FileLinedef* pLine, const Level* level, bool line_in_sector, VertexData to_, VertexData from_, int id);

    inline float x1 (void) const { return from.x; };
    inline float y1 (void) const { return from.y; };
    inline float x2 (void) const { return to.x; };
    inline float y2 (void) const { return to.y; };

    virtual bool IsTripLine (void) const;

    int num;

    int flags;

    int from_idx;
    int to_idx;

    VertexData from;
    VertexData to;

    float COS;           // which angle this is facing so we know when to draw floor etc.
    float SINE;          // the angle of the line from x1,y1 to x2,y2.
  
    float length;        // length of linedef
    float dist;          // distance of linedef to player

    Sector* sector;
    Sector* facingsector;

    short fwall_bitmap;          // fwall is the main wall
    short animation_end;         // the end of the animation cycle for the fwall
    short cwall_bitmap;           // cwall is for the "top slice".

    float fwall_u_offset;
    float fwall_v_offset;

    float cwall_u_offset;
    float cwall_v_offset;

    Line* nextline;   // next line in sector of this linedef

    int           num_floor_walls;
    int           num_ceil_walls;

    bool          generated;
    Line*         original_line;

//    Sector::Wall* walls;

    SectorWall* fwall;
    SectorWall* cwall;
  };

  class TripLine : public Line
  {
  public:
    TripLine (const FileLinedef* pLine, const Level* level, bool line_in_sector, VertexData to_, VertexData from_, int id);

    bool IsTripLine (void) const;

    enum ActionType {
      Teleport,
      Flip,         ///< Unused (Unknown)
      GoalPost,     ///< Unused
      LevelChange,
      SoundEffect,  ///< Unused
      ShowMessage,  ///< Unused
      QuestBuild    ///< Unused
    };

    enum EventType {
      Activate = 0x01,
      Cross    = 0x02
    };

  //private:
    int   trip_flags;
    short trip1;           // misc values for different trip wires.
    short trip2;
    short trip3;           // misc values for different trip wires.
    short trip4;

    ActionType action;  // What to do upon tripping the line
    int        event;   // Crossable or Activatable?
  };

  class LineList
  {
  public:
    void SetUsed (Line* line)
    {
      if (! IsUsed (line)) {
        used.push_back (line);
      }
    }

    bool IsUsed (Line* test) const
    {
      std::vector<Line*>::const_iterator line = used.begin ();
      std::vector<Line*>::const_iterator end  = used.end   ();

      while (eSTL::IterValid (line, end)) {
        if ((*line) == test) {
          return true;
        }

        ++line;
      }

      return false;
    }

    void Clear (void)
    {
      used.clear ();
    }

    std::vector <Line *> used;
  };

  // More or less a line factory...
  Line* CreateLine ( const FileLinedef* pLine,
                     const Level*       level,
                     bool               in_sector,
                     VertexData         v1,
                     VertexData         v2,
                     Line*              original = NULL,
                     int                id       = 0 );
};

#endif /* __CLI_PARSE__LINE_H__ */
